package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.abstracts.AbstractCrmAddDataService;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.data.service.CabinetFileService;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.AssociatedBusinessAfterSavePojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.pro.domain.entity.ReRollBackEntity;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.saas.domain.entity.RefundSubDataEntity;
import com.xbongbong.saas.domain.entity.ext.RefundEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.model.RefundModel;
import com.xbongbong.saas.model.RefundSubDataModel;
import com.xbongbong.saas.service.RefundService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;

/**
 *
 * @author 魏荣杰
 * @date 2021/1/4 15:42
 * @since
 * @version
 */
@Service("refundFormDataServiceImpl")
public class RefundFormDataServiceImpl extends AbstractCrmAddDataService {

    private static final Logger LOG = LoggerFactory.getLogger(RefundFormDataServiceImpl.class);
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private RefundModel refundModel;
    @Resource
    private RefundService refundService;
    @Resource
    private CabinetFileService cabinetFileService;
    @Resource
    private OperationLogFactory operationLogFactory;
    @Resource
    private DynamicHelp dynamicHelp;
    @Resource
    private RefundSubDataModel refundSubDataModel;

    @Override
    public List<Integer> businessList() {
        return Arrays.asList(XbbRefTypeEnum.REFUND.getCode());
    }

    @Override
    public SaveVO save(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            AssociatedBusinessAfterSavePojo refundAfterSavePojo = new AssociatedBusinessAfterSavePojo();
            if (Objects.equals(1, noApprovalRequired)) {
                RefundEntityExt refundEntityExt = new RefundEntityExt();
                BeanUtil.copyProperties(paasFormDataEntity, refundEntityExt);
                // 关联产品特殊处理
                JSONObject refundDataList = refundEntityExt.getData();
                JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(refundDataList, RefundEnum.PRODUCTS.getAttr());
                JSONArray invoiceArray = refundDataList.getJSONArray(RefundEnum.INVOICES.getAttr());
                JSONArray paymentSheetArray = refundDataList.getJSONArray(RefundEnum.PAYMENT_SHEETS.getAttr());
                JSONArray paymentArray = refundDataList.getJSONArray(RefundEnum.PAYMENTS.getAttr());
                saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.INVOICES.getAttr(), RefundEnum.INVOICES_LINKED_TEXT.getAttr(), RefundEnum.INVOICES.getFieldType());
                saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.PAYMENT_SHEETS.getAttr(), RefundEnum.PAYMENT_SHEETS_LINKED_TEXT.getAttr(), RefundEnum.PAYMENT_SHEETS.getFieldType());
                saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.PAYMENTS.getAttr(), RefundEnum.PAYMENTS_LINKED_TEXT.getAttr(), RefundEnum.PAYMENTS.getFieldType());
                //合计退款金额在afterSave中处理，根据回款单是否创建成功来处理
                Double refundAmount = getDoubleOrDefaultFromFormData(refundDataList, RefundEnum.REFUND_AMOUNT.getAttr(), 0D);
//                boolean paymentSheetIsProcess = processStartHelp.processFormJudge(corpid, XbbRefTypeEnum.PAYMENT_SHEET.getCode());
//                boolean invoiceIsProcess = processStartHelp.processFormJudge(corpid, XbbRefTypeEnum.INVOICE.getCode());
//                if (paymentSheetIsProcess) {
//                    refundDataList.put(RefundEnum.REFUND_AMOUNT.getAttr(), 0D);
//                }
                FormDataUtil.removeSystemData(refundDataList);
                Object richTextData = removeRichText(refundDataList);
                refundEntityExt.setData(refundDataList);
                refundModel.insert(refundEntityExt);
                dataId = refundEntityExt.getId();
                refundEntityExt.getData().put(RefundEnum.PRODUCTS.getAttr(),productArray);
                // 设置属性用于返回
                setPartialAttributes(dataId, refundEntityExt.getSubFormData(), refundEntityExt.getData(), refundEntityExt.getAddTime(),
                        refundEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
                refundAfterSavePojo = new AssociatedBusinessAfterSavePojo(invoiceArray, paymentSheetArray,paymentArray, refundAmount, new ReRollBackEntity(), null, null);
                //文件柜数据保存
                saveFile(formDataAddDTO, paasFormDataEntity, userVO);
                //富文本数据保存
                saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            }
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundAfterSavePojo);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void saveRollBack(Long dataId, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        try {
            IndexTypeEnum indexTypeEnum = getIndexTypeEnum(corpid, saasMark, businessType);
            //删除主表es数据
            physicalDeleteFormData(dataId, corpid, indexTypeEnum);
            // 子表单的删除
            List<RefundSubDataEntity> bomBillSubDataEntities = refundSubDataModel.getByDataId(dataId, corpid);
            if (CollectionsUtil.isNotEmpty(bomBillSubDataEntities)) {
                physicalDeleteSubBatch(corpid, bomBillSubDataEntities, IndexTypeEnum.IDX_SAAS_REFUND_SUB);
            }
        } catch (Exception e) {
            LOG.error("abstractFormDataServiceImpl.saveRollBack 回滚失败：", e);
        }

    }

    @Override
    public FormDataAddVO afterSave(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            if (Objects.equals(1, saveVO.getNoApprovalRequired())) {
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
                AssociatedBusinessAfterSavePojo refundAfterSavePojo = saveVO.getAssociatedBusinessAfterSavePojo();
                saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(beforeSaveVO.getSaasNeedRedundantAttrPojo());
                refundService.afterSave(saasFormSaveDTO, refundAfterSavePojo);

                // log
                afterSaveLog(formDataAddDTO, paasFormEntity, paasFormDataEntity, saveVO, beforeSaveVO);
                // 动态处理
                dynamicHelp.addLinkData(saasFormSaveDTO);
                // api
                apiHook(formDataAddDTO, saveVO, beforeSaveVO);
                // 业务规则
                activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
                formDataAddVO.setDataId(saveVO.getDataId());
                formDataAddVO.setFormDataId(saveVO.getDataId());
            } else {
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            }
            return formDataAddVO;
        }  catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void apiHook(FormDataAddDTO formDataAddDTO, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        lowCodeExecuteService(formDataAddDTO, saveVO, beforeSaveVO);
    }

    @Override
    public SaveVO saveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            AssociatedBusinessAfterSavePojo refundAfterSavePojo = new AssociatedBusinessAfterSavePojo();

            RefundEntityExt refundEntityExt = new RefundEntityExt();
            BeanUtil.copyProperties(paasFormDataEntity, refundEntityExt);
            // 关联产品特殊处理
            JSONObject refundDataList = refundEntityExt.getData();
            JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(refundDataList, RefundEnum.PRODUCTS.getAttr());
            JSONArray invoiceArray = refundDataList.getJSONArray(RefundEnum.INVOICES.getAttr());
            JSONArray paymentSheetArray = refundDataList.getJSONArray(RefundEnum.PAYMENT_SHEETS.getAttr());
            JSONArray paymentArray = refundDataList.getJSONArray(RefundEnum.PAYMENTS.getAttr());
            saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.INVOICES.getAttr(), RefundEnum.INVOICES_LINKED_TEXT.getAttr(), RefundEnum.INVOICES.getFieldType());
            saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.PAYMENT_SHEETS.getAttr(), RefundEnum.PAYMENT_SHEETS_LINKED_TEXT.getAttr(), RefundEnum.PAYMENT_SHEETS.getFieldType());
            saasSaveHelp.formatLinkBusiness4SaveBySerialNo(refundDataList, RefundEnum.PAYMENTS.getAttr(), RefundEnum.PAYMENTS_LINKED_TEXT.getAttr(), RefundEnum.PAYMENTS.getFieldType());

            //合计退款金额在afterSave中处理，根据回款单是否创建成功来处理
            Double refundAmount = getDoubleOrDefaultFromFormData(refundDataList, RefundEnum.REFUND_AMOUNT.getAttr(), 0D);
//            boolean paymentSheetIsProcess = processStartHelp.processFormJudge(corpid, XbbRefTypeEnum.PAYMENT_SHEET.getCode());
//            boolean invoiceIsProcess = processStartHelp.processFormJudge(corpid, XbbRefTypeEnum.INVOICE.getCode());
//            if (paymentSheetIsProcess) {
//                refundDataList.put(RefundEnum.REFUND_AMOUNT.getAttr(), 0D);
//            }
            FormDataUtil.removeSystemData(refundDataList);
            Object richTextData = removeRichText(refundDataList);
            refundEntityExt.setData(refundDataList);
            refundModel.insert(refundEntityExt);
            dataId = refundEntityExt.getId();

            refundEntityExt.getData().put(RefundEnum.PRODUCTS.getAttr(),productArray);
            refundEntityExt.getData().put(RefundEnum.INVOICES.getAttr(),invoiceArray);
            refundEntityExt.getData().put(RefundEnum.PAYMENT_SHEETS.getAttr(),paymentSheetArray);
            refundEntityExt.getData().put(RefundEnum.PAYMENTS.getAttr(),paymentArray);
            // 设置属性用于返回
            setPartialAttributes(dataId, refundEntityExt.getSubFormData(), refundEntityExt.getData(), refundEntityExt.getAddTime(), refundEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
            refundAfterSavePojo = new AssociatedBusinessAfterSavePojo(invoiceArray, paymentSheetArray, paymentArray, refundAmount, new ReRollBackEntity(), null, null);
            //文件柜数据保存
//            saveFile(formDataAddDTO, paasFormDataEntity, userVO);
            //富文本数据保存
            saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);

            paasFormDataEntity.getData().put(RefundEnum.PRODUCTS.getAttr(),productArray);
            paasFormDataEntity.getData().put(RefundEnum.INVOICES.getAttr(), invoiceArray);
            paasFormDataEntity.getData().put(RefundEnum.PAYMENT_SHEETS.getAttr(), paymentSheetArray);
            paasFormDataEntity.getData().put(RefundEnum.PAYMENTS.getAttr(), paymentArray);

            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundAfterSavePojo);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public FormDataAddVO afterSaveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
            packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
            AssociatedBusinessAfterSavePojo refundAfterSavePojo = saveVO.getAssociatedBusinessAfterSavePojo();
            saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(beforeSaveVO.getSaasNeedRedundantAttrPojo());
            refundService.afterSaveForWorkflow(saasFormSaveDTO, refundAfterSavePojo);

            // log
//            afterSaveLog(formDataAddDTO, paasFormDataEntity, saveVO, beforeSaveVO);
            // api
//            apiHook(formDataAddDTO, saveVO, beforeSaveVO);
            // 业务规则
//            activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());
            formDataAddVO.setDataId(saveVO.getDataId());
            formDataAddVO.setFormDataId(saveVO.getDataId());
            formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
            return formDataAddVO;
        }  catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }
}
